package com.acenodie.acenodieopenglturorial.Camera1Demo2;

import android.content.res.Resources;
import android.graphics.SurfaceTexture;
import android.opengl.GLES11Ext;
import android.opengl.GLES20;
import android.opengl.Matrix;
import android.util.Log;
import android.view.SurfaceHolder;

import com.acenodie.acenodieopenglturorial.filter.AFilter;
import com.acenodie.acenodieopenglturorial.filter.GPUImageFilter;
import com.acenodie.acenodieopenglturorial.filter.OesFilter;
import com.acenodie.acenodieopenglturorial.filter.VideoDrawFilter;
import com.acenodie.acenodieopenglturorial.filter.VideoMagicFilter;
import com.acenodie.acenodieopenglturorial.utils.Gl2Utils;

import java.util.List;

import javax.microedition.khronos.opengles.GL10;

/**
 * Created by zhangb2 on 17.6.7.
 */

public class CameraDrawer2 implements SurfaceHolder.Callback{
    public static final String TAG = "CameraDrawer2";

    private AFilter mOesFilter;
    private SurfaceTexture surfaceTexture;
    private int oesTextureId;

    private VideoMagicFilter mFilter = null;
    private VideoDrawFilter mOutFilter = null;
    private GPUImageFilter mCustomizeFilter = null;
    private List<GPUImageFilter> mCustomizeGroupFilters = null;


    private float[] matrix=new float[16];
    private int width,height;
    private int dataWidth,dataHeight;
    private int cameraId=1;

    public CameraDrawer2(Resources res){
        mOesFilter=new OesFilter(res);
    }

    public void setDataSize(int dataWidth,int dataHeight){
        this.dataWidth=dataWidth;
        this.dataHeight=dataHeight;
        calculateMatrix();
    }

    public void setViewSize(int width,int height){
        this.width=width;
        this.height=height;
        calculateMatrix();
    }

    public void setCameraId(int id){
        this.cameraId=id;
        calculateMatrix();
    }

    public SurfaceTexture getSurfaceTexture(){
        return surfaceTexture;
    }


    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        oesTextureId = createTextureID();
        surfaceTexture=new SurfaceTexture(oesTextureId);
        surfaceTexture.setOnFrameAvailableListener(new SurfaceTexture.OnFrameAvailableListener() {

            @Override
            public void onFrameAvailable(SurfaceTexture surfaceTexture) {
                Log.e(TAG, "onFrameAvailable: "+"...");
                tryDeliverTextureFrame();
            }
        });
        mOesFilter.create();
        mOesFilter.setTextureId(oesTextureId);
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        setViewSize(width,height);
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {

    }

    private int createTextureID(){
        int[] texture = new int[1];
        GLES20.glGenTextures(1, texture, 0);
        GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, texture[0]);
        GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
                GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_LINEAR);
        GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
                GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
        GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
                GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
        GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
                GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);
        return texture[0];
    }

    private void calculateMatrix(){
        Gl2Utils.getShowMatrix(matrix,this.dataWidth,this.dataHeight,this.width,this.height);
        if(cameraId==1){
            Gl2Utils.flip(matrix,true,false);
            Gl2Utils.rotate(matrix,90);
        }else{
            Gl2Utils.rotate(matrix,270);
        }
        mOesFilter.setMatrix(matrix);
    }

    private void tryDeliverTextureFrame(){
        if(surfaceTexture!=null){
            surfaceTexture.updateTexImage();
        }
        mOesFilter.draw();
        //renderOESTexture();
    }

    private void renderOESTexture(){
        if (mFilter == null) {
            mFilter = new VideoMagicFilter();
            mFilter.setFilter(mCustomizeFilter);
            mFilter.setFilter(mCustomizeGroupFilters);
            mFilter.initFilter();
        }
        mFilter.onFilterChanged(width, height, width, height);
        final float[] rotationMatrix = new float[16];
        Matrix.setRotateM(rotationMatrix, 0, 90, 0, 0, 1);
        int id = mFilter.onDrawFrame(oesTextureId, false, rotationMatrix);

        if (mOutFilter == null) {
            mOutFilter = new VideoDrawFilter();
            mOutFilter.initFilter();
        }
        mOutFilter.onFilterChanged(width, height, width, height);
        mOutFilter.setMirror(false);
        mOutFilter.onDrawFrame(id);
    }
}
